package questions;

import org.junit.jupiter.api.Test;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

public class OOMDemo {
    public void stackoverflow(Integer i){
        stackoverflow(++i);//Exception in thread "main" java.lang.StackOverflowError
    }
    @Test
    public void testStackoverflow(){
        stackoverflow(1);//Exception in thread "main" java.lang.StackOverflowError
    }
    /**
     * 测试1：只做OOM测试
     * -Xmx10m -Xms10m -XX:+PrintGCDetails
     * 测试2：观察JVM垃圾回收器SerialGC
     * -Xmx10m -Xms10m -XX:+PrintGCDetails  -XX:+UseSerialGC -XX:+PrintCommandLineFlags
     * 结果
     *   [GC (Allocation Failure) [DefNew: 2752K->319K(3072K), 0.0105972 secs] 2752K->909K(9920K), 0.0106494 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]
     *   [Full GC (Allocation Failure) [Tenured: 2633K->2137K(6848K), 0.0074308 secs] 2633K->2137K(9920K), [Metaspace: 8588K->8588K(1056768K)], 0.0074835 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]
     *   特征：
     *      DefNew
     *      Tenured
     * 测试3：观察JVM垃圾回收器ParNew
     * -Xmx10m -Xms10m -XX:+PrintGCDetails  -XX:+UseParNewGC -XX:+PrintCommandLineFlags
     * 结果
     *   [GC (Allocation Failure) [ParNew: 2752K->318K(3072K), 0.0120669 secs] 2752K->955K(9920K), 0.0121034 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]
     *   [Full GC (Allocation Failure) [Tenured: 2426K->2136K(6848K), 0.0068025 secs] 2426K->2136K(9920K), [Metaspace: 8582K->8582K(1056768K)], 0.0068576 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]      *   特征：
     *      ParNew
     *      Tenured
     *   Java HotSpot(TM) 64-Bit Server VM warning: Using the ParNew young collector with the Serial old collector is deprecated and will likely be removed in a future release
     *
     * 测试4：观察JVM垃圾回收器ParallelGC
     * -Xmx10m -Xms10m -XX:+PrintGCDetails  -XX:+UseParallelGC -XX:+PrintCommandLineFlags
     * 结果
     *   [GC (Allocation Failure) [PSYoungGen: 2048K->504K(2560K)] 2048K->868K(9728K), 0.0010094 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
     *   [Full GC (Allocation Failure) [PSYoungGen: 0K->0K(2048K)] [ParOldGen: 2507K->2333K(7168K)] 2507K->2333K(9216K), [Metaspace: 8578K->8552K(1056768K)], 0.0159681 secs] [Times: user=0.02 sys=0.00, real=0.02 secs]      *      ParNew
     *      PSYoungGen
     *      ParOldGen
     *
     * 测试5：观察JVM垃圾回收器ParallelOldGC
     * -Xmx10m -Xms10m -XX:+PrintGCDetails  -XX:+UseParallelOldGC -XX:+PrintCommandLineFlags
     * 结果
     *   [GC (Allocation Failure) [PSYoungGen: 2048K->504K(2560K)] 2048K->868K(9728K), 0.0010094 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
     *   [Full GC (Allocation Failure) [PSYoungGen: 0K->0K(2048K)] [ParOldGen: 2507K->2333K(7168K)] 2507K->2333K(9216K), [Metaspace: 8578K->8552K(1056768K)], 0.0159681 secs] [Times: user=0.02 sys=0.00, real=0.02 secs]      *      ParNew
     *      PSYoungGen
     *      ParOldGen
     *
     * 测试6：观察JVM垃圾回收器UseConcMarkSweep
     * -Xmx10m -Xms10m -XX:+PrintGCDetails  -XX:+UseConcMarkSweepGC -XX:+PrintCommandLineFlags
     * 结果
     *   [GC (Allocation Failure) [ParNew: 2752K->320K(3072K), 0.0014672 secs] 2752K->933K(9920K), 0.0015211 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
     *      ParNew
     *   [GC (CMS Initial Mark) [1 CMS-initial-mark: 5326K(6848K)] 6864K(9920K), 0.0003465 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
     *   [CMS-concurrent-mark-start]
     *   [CMS-concurrent-mark: 0.002/0.002 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
     *   [CMS-concurrent-preclean-start]
     *   [CMS-concurrent-preclean: 0.000/0.000 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
     *   [GC (CMS Final Remark) [YG occupancy: 1538 K (3072 K)][Rescan (parallel) , 0.0001297 secs][weak refs processing, 0.0000110 secs][class unloading, 0.0007797 secs][scrub symbol table, 0.0005654 secs][scrub string table, 0.0001058 secs][1 CMS-remark: 5326K(6848K)] 6864K(9920K), 0.0016394 secs] [Times: user=0.03 sys=0.00, real=0.00 secs]
     *   [CMS-concurrent-sweep-start]
     *   [Full GC (Allocation Failure) [CMS: 5237K->5060K(6848K), 0.0063866 secs] 5237K->5060K(9920K), [Metaspace: 8599K->8599K(1058816K)], 0.0064310 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]
     *      CMS
     *
     * 测试7：观察JVM 垃圾回收器
     * -Xmx10m -Xms10m -XX:+PrintGCDetails -XX:+PrintCommandLineFlags -XX:+UseG1GC -XX:MaxGCPauseMillis=100
     */
    @Test
    public void javaheapspace(){
        String str="xfadfa";
        while (true){
            str+=str;
//            str.intern();
        }
//        byte[]arr=new byte[20*1024*1024];
    }

    /**
     * -Xmx10m -Xms10m -XX:+PrintGCDetails
     */
    @Test
    public void gcOverheadLimit(){
        List<String>  stringList = new ArrayList<>();
        Integer i =0;
        try {
            while (true){
                stringList.add(String.valueOf(++i).intern());
            }
        }catch (Throwable e){
            System.out.println(i);
            throw e;
        }
    }
    /**
     * -Xmx10m -Xms10m -XX:+PrintGCDetails -XX:MaxDirectMemorySize=5m
     */
    @Test
    public void directBufferMemory(){
        ByteBuffer.allocateDirect(6*1024*1024);
    }
    /**
     * -Xmx10m -Xms10m -XX:+PrintGCDetails -XX:MaxDirectMemorySize=5m
     * window上，这个东西可能没限制，运行需要谨慎
     */
    @Test
    public void cantCreateNewNativeThread(){
        for (int i = 0;; i++) {
            new Thread(()->{
                try {
                    TimeUnit.SECONDS.sleep(Integer.MAX_VALUE);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }).start();

        }
    }
    /**
     * -XX:+PrintGCDetails  -XX:MaxMetaspaceSize=6m -XX:MetaspaceSize=8m
     */
    @Test
    public void metaSpace(){
        int i=1;
        while (true){
            i++;
            Enhancer enhancer = new Enhancer();
            enhancer.setCallback((MethodInterceptor) (o, method, objects, methodProxy) -> methodProxy.invokeSuper(o,objects));
            enhancer.setSuperclass(MyParent.class);
            enhancer.setUseCache(false);
            enhancer.create();
        }
    }
    class MyParent{
    }
}

